float4x4 World;
float4x4 View;
float4x4 Projection;

float SpecularIntensity = 0.8f;
float SpecularPower = 0.5f;

texture Texture;
texture NormalMap;
texture SpecularMap;

sampler SpecularSampler = sampler_state
{
    Texture = (SpecularMap);
    MagFilter = LINEAR;
    MinFilter = LINEAR;
    Mipfilter = LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;
};

sampler NormalSampler = sampler_state
{
    Texture = (NormalMap);
    MagFilter = LINEAR;
    MinFilter = LINEAR;
    Mipfilter = LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;
};

sampler DiffuseSampler = sampler_state
{
    Texture = (Texture);
    MAGFILTER = LINEAR;
    MINFILTER = LINEAR;
    MIPFILTER = LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;
};

struct VertexShaderInput
{
    float4 Position : POSITION0;
	float3 Normal : NORMAL0;
    float2 TexCoord : TEXCOORD0;
    float3 Binormal : BINORMAL0;
    float3 Tangent : TANGENT0;
};

struct VertexShaderOutput
{
    float4 Position : POSITION0;
    float2 TexCoord : TEXCOORD0;
    //float3 Normal : TEXCOORD1;
    float2 Depth : TEXCOORD1;
    float3x3 TangentToWorld : TEXCOORD2;
};

struct PixelShaderOutput
{
    half4 Colour : COLOR0;
    half4 Normal : COLOR1;
    half4 Depth : COLOR2;
};

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
    VertexShaderOutput Output;

    float4 WorldPosition = mul(input.Position, World);
    float4 ViewPosition = mul(WorldPosition, View);
    Output.Position = mul(ViewPosition, Projection);

    Output.TexCoord = input.TexCoord;

    //Output.Normal = mul(input.Normal,World);

    Output.Depth.x = Output.Position.z;
    Output.Depth.y = Output.Position.w;
    
    // calculate tangent space to world space matrix using the world space tangent,
    // binormal, and normal as basis vectors
    Output.TangentToWorld[0] = mul(input.Tangent, World);
    Output.TangentToWorld[1] = mul(input.Binormal, World);
    Output.TangentToWorld[2] = mul(input.Normal, World);

    return Output;
}

PixelShaderOutput PixelShaderFunction(VertexShaderOutput input)
{
    PixelShaderOutput Output;

	//output colour
    Output.Colour = tex2D(DiffuseSampler, input.TexCoord);


	/*
	//output specular intensity
    Output.Colour.a = SpecularIntensity;

	//normals are transformed from [0,1] to [-1,1] domain
    Output.Normal.rgb = 0.5f * (normalize(input.Normal) + 1.0f);

	//output specular power
    Output.Normal.a = SpecularPower;

	//output the depth value
    Output.Depth = input.Depth.x / input.Depth.y;

    return Output;*/
    
    
    float4 SpecularAttributes = tex2D(SpecularSampler, input.TexCoord);

    //specular Intensity
    Output.Colour.a = SpecularAttributes.r;

    // read the normal from the normal map
    float3 NormalFromMap = tex2D(NormalSampler, input.TexCoord);

    //transform to [-1,1]
    NormalFromMap = 2.0f * NormalFromMap - 1.0f;

    //transform into world space
    NormalFromMap = mul(NormalFromMap, input.TangentToWorld);

    //normalize the result
    NormalFromMap = normalize(NormalFromMap);

    //output the normal, in [0,1] space
    Output.Normal.rgb = 0.5f * (NormalFromMap + 1.0f);

    //specular Power
    Output.Normal.a = SpecularAttributes.a;

    Output.Depth = input.Depth.x / input.Depth.y;

    return Output;
}

technique Technique1
{
    pass Pass1
    {
        VertexShader = compile vs_2_0 VertexShaderFunction();
        PixelShader = compile ps_2_0 PixelShaderFunction();
    }
}
